//------------------------------------------------------------------------------
// The contents of this file are title to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at  http://www.nopCommerce.com/License.aspx. 
// 
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 
// See the License for the specific language governing rights and limitations under the License.
// 
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
// 
// Contributor(s): _______. 
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Caching;
using NopSolutions.NopCommerce.BusinessLogic.Data;
using NopSolutions.NopCommerce.BusinessLogic.Infrastructure.Caching;
using NopSolutions.NopCommerce.BusinessLogic.Model;
using NopSolutions.NopCommerce.Common.Utils;

namespace NopSolutions.NopCommerce.BusinessLogic.Services.Implementation
{
    /// <summary>
    /// Message service
    /// </summary>
    public partial class TopicService : ITopicService
    {
        #region Fields

        private const string TOPIC_CACHE_KEYS = "TOPIC_CACHE_KEY_{0}";
        private const string LOCALIZED_TOPIC_CACHE_KEYS = "LOCALIZED_TOPIC_CACHE_KEY_{0}";

        /// <summary>
        /// Object context
        /// </summary>
        private readonly NopObjectContext _context;

        /// <summary>
        /// Cache manager
        /// </summary>
        private readonly ICacheManager _cacheManager;

        #endregion

        #region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="context">Object context</param>
        public TopicService(NopObjectContext context, ICacheManager cacheManager) {
            this._context = context;
            this._cacheManager = cacheManager;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Deletes a topic
        /// </summary>
        /// <param name="topicId">Topic identifier</param>
        public void DeleteTopic(int topicId) {
            var topic = GetTopicById(topicId);
            if (topic == null)
                return;

            if (!_context.IsAttached(topic))
                _context.Topics.Attach(topic);
            _context.DeleteObject(topic);

            int result = _context.SaveChanges();

            if (result > 0) {
                _cacheManager.Remove(string.Format(TOPIC_CACHE_KEYS, topic));
            }
        }

        /// <summary>
        /// Inserts a topic
        /// </summary>
        /// <param name="topic">Topic</param>
        public void InsertTopic(Topic topic) {
            if (topic == null)
                throw new ArgumentNullException("topic");

            topic.Name = CommonHelper.EnsureNotNull(topic.Name);
            topic.Name = CommonHelper.EnsureMaximumLength(topic.Name, 200);
            topic.Password = CommonHelper.EnsureNotNull(topic.Password);
            topic.Password = CommonHelper.EnsureMaximumLength(topic.Password, 200);

            _context.Topics.AddObject(topic);
            int result = _context.SaveChanges();

            if (result > 0) {
                _cacheManager.Add(string.Format(TOPIC_CACHE_KEYS, topic.TopicId), topic, null, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0));
            }
        }

        /// <summary>
        /// Updates the topic
        /// </summary>
        /// <param name="topic">Topic</param>
        public void UpdateTopic(Topic topic) {
            if (topic == null)
                throw new ArgumentNullException("topic");

            topic.Name = CommonHelper.EnsureNotNull(topic.Name);
            topic.Name = CommonHelper.EnsureMaximumLength(topic.Name, 200);
            topic.Password = CommonHelper.EnsureNotNull(topic.Password);
            topic.Password = CommonHelper.EnsureMaximumLength(topic.Password, 200);

            var contextTopic = _context.Topics.Where(t => t.TopicId == topic.TopicId).SingleOrDefault();
            if (contextTopic != null) {
                _context.ObjectStateManager.GetObjectStateEntry(contextTopic).ApplyCurrentValues(topic);

                //if (!_context.IsAttached(topic))
                //    _context.Topics.Attach(topic);

                int result = _context.SaveChanges();

                if (result > 0) {
                    _cacheManager.Remove(string.Format(TOPIC_CACHE_KEYS, topic.TopicId));
                    _cacheManager.Add(string.Format(TOPIC_CACHE_KEYS, topic.TopicId), topic);
                }
            }
        }

        /// <summary>
        /// Gets a topic by template identifier
        /// </summary>
        /// <param name="topicId">topic identifier</param>
        /// <returns>topic</returns>
        public Topic GetTopicById(int topicId) {
            if (topicId == 0)
                return null;

            string key = string.Format(TOPIC_CACHE_KEYS, topicId);

            Topic cachedTopic = _cacheManager.Get(key) as Topic;
            if (cachedTopic != null) {
                return cachedTopic;
            }

            var topic = TopicCompiledQueries.TopicById.Invoke(_context, topicId);

            _cacheManager.Add(key, topic, null, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0));

            return topic;
        }

        /// <summary>
        /// Gets all topics
        /// </summary>
        /// <returns>topic collection</returns>
        public List<Topic> GetAllTopics() {
            return TopicCompiledQueries.Topics.Invoke(_context).ToList();
        }

        /// <summary>
        /// Gets a localized topic by identifier
        /// </summary>
        /// <param name="localizedTopicId">Localized topic identifier</param>
        /// <returns>Localized topic</returns>
        public LocalizedTopic GetLocalizedTopicById(int localizedTopicId) {
            if (localizedTopicId == 0)
                return null;

            string key = string.Format(LOCALIZED_TOPIC_CACHE_KEYS, localizedTopicId);

            LocalizedTopic cachedLocalizedTopic = _cacheManager.Get(key) as LocalizedTopic;
            if (cachedLocalizedTopic != null) {
                return cachedLocalizedTopic;
            }

            var localizedTopic = TopicCompiledQueries.LocalizedTopicById.Invoke(_context, localizedTopicId);

            _cacheManager.Add(key, localizedTopic, null, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0));

            return localizedTopic;
        }

        /// <summary>
        /// Gets a localized topic by parent topic identifier and language identifier
        /// </summary>
        /// <param name="topicId">The topic identifier</param>
        /// <param name="languageId">Language identifier</param>
        /// <returns>Localized topic</returns>
        public LocalizedTopic GetLocalizedTopic(int topicId, int languageId) {

            string key = string.Format(LOCALIZED_TOPIC_CACHE_KEYS, topicId);

            LocalizedTopic cachedLocalizedTopic = _cacheManager.Get(key) as LocalizedTopic;
            if (cachedLocalizedTopic != null) {
                return cachedLocalizedTopic;
            }

            var localizedTopic = TopicCompiledQueries.LocalizedTopicByTopicAndLanguage.Invoke(_context, topicId, languageId);

            _cacheManager.Add(key, localizedTopic, null, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0));

            return localizedTopic;
        }

        /// <summary>
        /// Gets a localized topic by name and language identifier
        /// </summary>
        /// <param name="topicName">Topic name</param>
        /// <param name="languageId">Language identifier</param>
        /// <returns>Localized topic</returns>
        public LocalizedTopic GetLocalizedTopic(string topicName, int languageId) {
            return TopicCompiledQueries.LocalizedTopicByTopicNameAndLanguageId.Invoke(_context, topicName, languageId);
        }

        /// <summary>
        /// Deletes a localized topic
        /// </summary>
        /// <param name="localizedTopicId">topic identifier</param>
        public void DeleteLocalizedTopic(int localizedTopicId) {
            var localizedTopic = GetLocalizedTopicById(localizedTopicId);
            if (localizedTopic == null)
                return;

            if (!_context.IsAttached(localizedTopic))
                _context.LocalizedTopics.Attach(localizedTopic);

            _context.DeleteObject(localizedTopic);

            int result = _context.SaveChanges();

            if (result > 0)
                _cacheManager.Remove(string.Format(LOCALIZED_TOPIC_CACHE_KEYS, localizedTopicId));
        }

        /// <summary>
        /// Gets all localized topics
        /// </summary>
        /// <param name="topicName">topic name</param>
        /// <returns>Localized topic collection</returns>
        public List<LocalizedTopic> GetAllLocalizedTopics(string topicName) {

            var query = from tl in _context.LocalizedTopics
                        join t in _context.Topics on tl.TopicId equals t.TopicId
                        where t.Name == topicName
                        orderby tl.LanguageId
                        select tl;
            var localizedTopics = query.ToList();
            return localizedTopics;
        }

        /// <summary>
        /// Inserts a localized topic
        /// </summary>
        /// <param name="localizedTopic">Localized topic</param>
        public void InsertLocalizedTopic(LocalizedTopic localizedTopic) {
            if (localizedTopic == null)
                throw new ArgumentNullException("localizedTopic");

            localizedTopic.Title = CommonHelper.EnsureNotNull(localizedTopic.Title);
            localizedTopic.Title = CommonHelper.EnsureMaximumLength(localizedTopic.Title, 200);
            localizedTopic.Body = CommonHelper.EnsureNotNull(localizedTopic.Body);
            localizedTopic.MetaTitle = CommonHelper.EnsureNotNull(localizedTopic.MetaTitle);
            localizedTopic.MetaTitle = CommonHelper.EnsureMaximumLength(localizedTopic.MetaTitle, 400);
            localizedTopic.MetaKeywords = CommonHelper.EnsureNotNull(localizedTopic.MetaKeywords);
            localizedTopic.MetaKeywords = CommonHelper.EnsureMaximumLength(localizedTopic.MetaKeywords, 400);
            localizedTopic.MetaDescription = CommonHelper.EnsureNotNull(localizedTopic.MetaDescription);
            localizedTopic.MetaDescription = CommonHelper.EnsureMaximumLength(localizedTopic.MetaDescription, 4000);

            _context.LocalizedTopics.AddObject(localizedTopic);
            int result = _context.SaveChanges();

            if (result > 0)
                _cacheManager.Add(string.Format(LOCALIZED_TOPIC_CACHE_KEYS, localizedTopic), localizedTopic, null, Cache.NoAbsoluteExpiration, new TimeSpan(1, 0, 0));
        }

        /// <summary>
        /// Updates the localized topic
        /// </summary>
        /// <param name="localizedTopic">Localized topic</param>
        public void UpdateLocalizedTopic(LocalizedTopic localizedTopic) {
            if (localizedTopic == null)
                throw new ArgumentNullException("localizedTopic");

            localizedTopic.Title = CommonHelper.EnsureNotNull(localizedTopic.Title);
            localizedTopic.Title = CommonHelper.EnsureMaximumLength(localizedTopic.Title, 200);
            localizedTopic.Body = CommonHelper.EnsureNotNull(localizedTopic.Body);
            localizedTopic.MetaTitle = CommonHelper.EnsureNotNull(localizedTopic.MetaTitle);
            localizedTopic.MetaTitle = CommonHelper.EnsureMaximumLength(localizedTopic.MetaTitle, 400);
            localizedTopic.MetaKeywords = CommonHelper.EnsureNotNull(localizedTopic.MetaKeywords);
            localizedTopic.MetaKeywords = CommonHelper.EnsureMaximumLength(localizedTopic.MetaKeywords, 400);
            localizedTopic.MetaDescription = CommonHelper.EnsureNotNull(localizedTopic.MetaDescription);
            localizedTopic.MetaDescription = CommonHelper.EnsureMaximumLength(localizedTopic.MetaDescription, 4000);

            if (!_context.IsAttached(localizedTopic)) {
                _context.LocalizedTopics.Attach(localizedTopic);
            }

            //var contextTopic = _context.LocalizedTopics.Where(t => t.TopicLocalizedId == localizedTopic.TopicLocalizedId).SingleOrDefault();
            //if (contextTopic != null) {
                //_context.ObjectStateManager.GetObjectStateEntry(contextTopic).ApplyCurrentValues(localizedTopic);
            {
                int result = _context.SaveChanges();

                if (result > 0) {
                    _cacheManager.Remove(string.Format(LOCALIZED_TOPIC_CACHE_KEYS, localizedTopic));
                    _cacheManager.Add(string.Format(LOCALIZED_TOPIC_CACHE_KEYS, localizedTopic), localizedTopic);
                }
            }
        }

        #endregion
    }
}